  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">















 
 
 
 
 
 
 
  
  


<html>
  <head>
    <script type="text/javascript" language="JavaScript">
    ORIGINAL_PAGE_PATH = "/appengine/articles/shelftalkers.html";
    </script>
    
    
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>HOWTO: Create a Facebook App with Google App Engine and Best Buy Remix - Google App Engine - Google Code</title>
<script type="text/javascript"><!--
(function(){function a(){this.t={};this.tick=function(c){this.t[c]=(new Date).getTime()};this.tick("start")}var b=new a;window.jstiming={Timer:a,load:b};if(window.external&&window.external.pageT)window.jstiming.pt=window.external.pageT;})();

var _tocPath_ = '/appengine/docs/_toc.ezt';
var codesite_token = null;
//--></script>
<link href="../../css/codesite.pack.04102009.css" type="text/css" rel="stylesheet"></link>
<script src="../../js/codesite_head.pack.04102009.js" type="text/javascript"></script>
<script type="text/javascript">CODESITE_CSITimer['load'].tick('bhs');</script>
<link rel="search" type="application/opensearchdescription+xml" title="Google Code" href="http://code.google.com/osd.xml" />

<!--[if IE]><link rel="stylesheet" type="text/css" href="../../css/iehacks.css" /><![endif]-->

    <link href="../../css/semantic_headers.css" rel="stylesheet" type="text/css" />
    <link href="../css/local_extensions.css" rel="stylesheet" type="text/css" />
  </head>

  <body class="gc-documentation">

    
    
    
</a>

<div id="gb">
 <span>
  
    <a id="lang-dropdown" class="dropdown" href="http://code.google.com" onclick="return false;"><img class="globeicon" src="../../images/globe2_small.png"/><span>English</span></a>
  
 </span>
</div>

<div class="gbh" style="left: 0pt;"></div>
<div class="gbh" style="right: 0pt;"></div>


<style type="text/css">
  #gc-topnav h1 {
    padding: 0 0 0 6px;
  }
</style>


<div id="gc-container">
<a name="top"></a>
<div id="skipto">
  <a href="#gc-pagecontent-anchor">Skip to page content</a>
  <a href="#gc-toc-anchor">Skip to main navigation</a>
</div>

<div id="gc-header">
  <div id="logo"><a href="http://code.google.com">
  
  
     <img src="../../images/cleardot.gif" height="1px" width="1px" alt="Google Code Home Page" id="gc-logo-img"/>
  
  
  </a></div>
  <div id="search">
    <div id="searchForm" class="searchForm">
      <form id="cse" action="http://www.google.com/cse" accept-charset="utf-8" class="gsc-search-box" onsubmit="executeGSearch(document.getElementById('gsearchInput').value); return false;">
      <noscript>
      <input type="hidden" name="cref" value="http://code.google.com/cse/googlecode-context.xml"/>
      </noscript>
        <table class="gsc-search-box" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td class="gsc-input">
                <input id="gsearchInput" type="text" name="q" maxlength="2048" class="gsc-input" autocomplete="off" title="Google Code Search" style="width:345px"/>
              </td>
              <td class="gsc-search-button">
                <div id="cs-searchresults" onclick="event.cancelBubble = true;"></div>
                <input title="Search" id="gsearchButton" class="gsc-search-button" name="sa" value="Search" type="submit"/>
              </td>
            </tr>
            <tr>
              <td colspan="2" class="greytext">e.g. "templates" or "datastore"</td>
            </tr>
          </tbody>
        </table>
      </form>
    </div> <!-- end searchForm -->
  </div> <!-- end search -->
</div> <!-- end gc-header -->


<div id="codesiteContent">

<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
  <h1>Google App Engine</h1>
  <ul id="articles" class="gc-topnav-tabs">

    <li id="home_link">
      <a href="../index.html" title="Google App Engine home page">Home</a>
    </li>
  
    <li id="docs_link">
      <a href="../docs/index.html" title="Official Google App Engine documentation">Docs</a>
    </li>
  
    <li id="faq_link">
      <a href="../kb/index.html" title="Answers to frequently asked questions about Google App Engine">FAQ</a>
    </li>
  
    <li id="articles_link">
      <a href="index.html" class="selected" title="Focused articles and tutorials for Google App Engine developers">Articles</a>
    </li>
  
    <li>
      <a href="http://googleappengine.blogspot.com/" title="Official Google App Engine blog">Blog</a>
    </li>
  
    <li>
      <a href="../community.html" title="Community home for Google App Engine">Community</a>
    </li>
  
    <li>
      <a href="../terms.html" title="Google App Engine terms of service">Terms</a>
    </li>
  
    <li>
      <a href="../downloads.html" title="Download Google App Engine">Download</a>
    </li>
  

  </ul>
</div> <!-- end gc-topnav -->

    <div class="g-section g-tpl-170">

      <a name="gc-toc-anchor"></a>  
      <div class="g-unit g-first" id="gc-toc">
        <ul>
  <li><a href="../downloads.html">Downloads</a></li>
  <li><a href="http://code.google.com/status/appengine">System Status</a></li>
  <li><a href="http://code.google.com/p/googleappengine/issues/list">Issue Tracker</a></li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Getting Started</h2>
    <ul>
      <li><a href="../docs/whatisgoogleappengine.html">What Is Google App Engine?</a></li>
      <li><a href="../docs/java/gettingstarted/index.html">Java</a>
        <ul>
              <li><a href="../docs/java/gettingstarted/introduction.html">Introduction</a></li>
    <li><a href="../docs/java/gettingstarted/installing.html">Installing the Java SDK</a></li>
    <li><a href="../docs/java/gettingstarted/creating.html">Creating a Project</a></li>
    <li><a href="../docs/java/gettingstarted/usingusers.html">Using the Users Service</a></li>
    <li><a href="../docs/java/gettingstarted/usingjsps.html">Using JSPs</a></li>
    <li><a href="../docs/java/gettingstarted/usingdatastore.html">Using the Datastore with JDO</a></li>
    <li><a href="../docs/java/gettingstarted/staticfiles.html">Using Static Files</a></li>
    <li><a href="../docs/java/gettingstarted/uploading.html">Uploading Your Application</a></li>

        </ul>
      </li>
      <li><a href="../docs/python/gettingstarted/index.html">Python</a>
        <ul>
            <li><a href="../docs/python/gettingstarted/introduction.html">Introduction</a></li>
  <li><a href="../docs/python/gettingstarted/devenvironment.html">The Development Environment</a></li>
  <li><a href="../docs/python/gettingstarted/helloworld.html">Hello, World!</a></li>
  <li><a href="../docs/python/gettingstarted/usingwebapp.html">Using the webapp Framework</a></li>
  <li><a href="../docs/python/gettingstarted/usingusers.html">Using the Users Service</a></li>
  <li><a href="../docs/python/gettingstarted/handlingforms.html">Handling Forms With webapp</a></li>
  <li><a href="../docs/python/gettingstarted/usingdatastore.html">Using the Datastore</a></li>
  <li><a href="../docs/python/gettingstarted/templates.html">Using Templates</a></li>
  <li><a href="../docs/python/gettingstarted/staticfiles.html">Using Static Files</a></li>
  <li><a href="../docs/python/gettingstarted/uploading.html">Uploading Your Application</a></li>

        </ul>
      </li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Java <sup class="new">Early Look</sup></h2>
    <ul>
          <li><a href="../docs/java/overview.html">Overview</a></li>
    <li><a href="../docs/java/runtime.html">Servlet Environment</a></li>
    <li><a href="../docs/java/datastore/index.html">Storing Data</a>
      <ul>
            <li><a href="../docs/java/datastore/overview.html">Overview</a></li>
    <li><a href="../docs/java/datastore/usingjdo.html">Using JDO</a></li>
    <li><a href="../docs/java/datastore/dataclasses.html">Defining Data Classes</a></li>
    <li><a href="../docs/java/datastore/creatinggettinganddeletingdata.html">Creating, Getting and Deleting Data</a></li>
    <li><a href="../docs/java/datastore/queriesandindexes.html">Queries and Indexes</a></li>
    <li><a href="../docs/java/datastore/transactions.html">Transactions</a></li>
    <li><a href="../docs/java/datastore/relationships.html">Relationships</a></li>
    <li><a href="../docs/java/datastore/usingjpa.html">Using JPA</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/datastore/package-summary.html">Low-level API</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/apis.html">Services</a>
      <ul>
        <li><a href="../docs/java/memcache/index.html">Memcache</a>
          <ul>
                <li><a href="../docs/java/memcache/overview.html">Overview</a></li>
    <li><a href="../docs/java/memcache/usingjcache.html">Using JCache</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/memcache/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/urlfetch/index.html">URL Fetch</a>
          <ul>
                <li><a href="../docs/java/urlfetch/overview.html">Overview</a></li>
    <li><a href="../docs/java/urlfetch/usingjavanet.html">Using java.net</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/urlfetch/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/mail/index.html">Mail</a>
          <ul>
                <li><a href="../docs/java/mail/overview.html">Overview</a></li>
    <li><a href="../docs/java/mail/usingjavamail.html">Using JavaMail</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/mail/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/images/index.html">Images</a>
          <ul>
                <li><a href="../docs/java/images/overview.html">Overview</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/images/package-summary.html">API Reference</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/users/index.html">Google Accounts</a>
          <ul>
                <li><a href="../docs/java/users/overview.html">Overview</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/users/package-summary.html">API Reference</a></li>

          </ul>
        </li>
      </ul>
    </li>
    <li><a href="../docs/java/javadoc/index.html">Javadoc Reference</a></li>
    <li><a href="../docs/java/jrewhitelist.html">JRE Class White List</a></li>
    <li><a href="../docs/java/config/index.html">Configuration</a>
      <ul>
            <li><a href="../docs/java/config/webxml.html">Deployment Descriptor</a></li>
    <li><a href="../docs/java/config/appconfig.html">App Config</a></li>
    <li><a href="../docs/java/config/indexconfig.html">Index Config</a></li>
    <li><a href="../docs/java/config/cron.html">Scheduled Tasks</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/tools/index.html">Tools</a>
      <ul>
            <li><a href="../docs/java/tools/devserver.html">Development Server</a></li>
    <li><a href="../docs/java/tools/uploadinganapp.html">Uploading and Managing</a></li>
    <li><a href="../docs/java/tools/eclipse.html">Google Plugin for Eclipse</a></li>
    <li><a href="../docs/java/tools/ant.html">Using Apache Ant</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/howto/index.html">How-To</a>
      <ul>
              <li><a href="../docs/java/howto/unittesting.html">Unit Testing</a></li>

      </ul>
    </li>

    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Python</h2>
    <ul>
          <li><a href="../docs/python/overview.html">Overview</a></li>
    <li><a href="../docs/python/runtime.html">CGI Environment</a></li>
    <li><a href="../docs/python/datastore/index.html">Storing Data</a>
      <ul>
             <li><a href="../docs/python/datastore/overview.html">Overview</a></li>
     <li><a href="../docs/python/datastore/entitiesandmodels.html">Entities and Models</a></li>
     <li><a href="../docs/python/datastore/creatinggettinganddeletingdata.html">Creating, Getting and Deleting Data</a></li>
     <li><a href="../docs/python/datastore/keysandentitygroups.html">Keys and Entity Groups</a></li>
     <li><a href="../docs/python/datastore/queriesandindexes.html">Queries and Indexes</a></li>
     <li><a href="../docs/python/datastore/transactions.html">Transactions</a></li>
     <li><a href="../docs/python/datastore/typesandpropertyclasses.html">Types and Property Classes</a></li>
     <li><a href="../docs/python/datastore/gqlreference.html">GQL Reference</a></li>

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/datastore/modelclass.html">Model</a></li>
         <li><a href="../docs/python/datastore/expandoclass.html">Expando</a></li>
         <li><a href="../docs/python/datastore/polymodelclass.html">PolyModel</a></li>
         <li><a href="../docs/python/datastore/propertyclass.html">Property</a></li>
         <li><a href="../docs/python/datastore/queryclass.html">Query</a></li>
         <li><a href="../docs/python/datastore/gqlqueryclass.html">GqlQuery</a></li>
         <li><a href="../docs/python/datastore/keyclass.html">Key</a></li>
         <li><a href="../docs/python/datastore/functions.html">Functions</a></li>
         <li><a href="../docs/python/datastore/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

      </ul>
    </li>
    <li><a href="../docs/python/apis.html">Services</a>
      <ul>
        <li><a href="../docs/python/memcache/index.html">Memcache</a>
          <ul>
                 <li><a href="../docs/python/memcache/overview.html">Overview</a></li>
      <li><a href="../docs/python/memcache/usingmemcache.html">Using Memcache</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/memcache/clientclass.html">Client</a></li>
         <li><a href="../docs/python/memcache/functions.html">Functions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/urlfetch/index.html">URL Fetch</a>
          <ul>
                 <li><a href="../docs/python/urlfetch/overview.html">Overview</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/urlfetch/fetchfunction.html">The fetch Function</a></li>
         <li><a href="../docs/python/urlfetch/responseobjects.html">Response Objects</a></li>
         <li><a href="../docs/python/urlfetch/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/mail/index.html">Mail</a>
          <ul>
                 <li><a href="../docs/python/mail/overview.html">Overview</a></li>
     <li><a href="../docs/python/mail/sendingmail.html">Sending Mail</a></li>
     <li><a href="../docs/python/mail/attachments.html">Attachments</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/mail/emailmessageclass.html">EmailMessage</a></li>
         <li><a href="../docs/python/mail/emailmessagefields.html">Message Fields</a></li>
         <li><a href="../docs/python/mail/functions.html">Functions</a></li>
         <li><a href="../docs/python/mail/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/images/index.html">Images</a>
          <ul>
                 <li><a href="../docs/python/images/overview.html">Overview</a></li>
     <li><a href="../docs/python/images/installingPIL.html">Installing PIL</a></li>
     <li><a href="../docs/python/images/usingimages.html">Using the Images API</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/images/imageclass.html">Image</a></li>
         <li><a href="../docs/python/images/functions.html">Functions</a></li>
         <li><a href="../docs/python/images/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/users/index.html">Google Accounts</a>
          <ul>
                 <li><a href="../docs/python/users/overview.html">Overview</a></li>
     <li><a href="../docs/python/users/userobjects.html">User Objects</a></li>
     <li><a href="../docs/python/users/loginurls.html">Login URLs</a></li>
     <li><a href="../docs/python/users/adminusers.html">Admin Users</a></li>

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/users/userclass.html">User</a></li>
         <li><a href="../docs/python/users/functions.html">Functions</a></li>
         <li><a href="../docs/python/users/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
      </ul>
    </li>
    <li><a href="../docs/python/config/index.html">Configuration</a>
      <ul>
            <li><a href="../docs/python/config/appconfig.html">App Config</a></li>
    <li><a href="../docs/python/config/indexconfig.html">Index Config</a></li>
    <li><a href="../docs/python/config/cron.html">Scheduled Tasks</a></li>

      </ul>
    </li>
    <li><a href="../docs/python/tools/index.html">Tools</a>
      <ul>
            <li><a href="../docs/python/tools/devserver.html">Development Server</a></li>
    <li><a href="../docs/python/tools/uploadinganapp.html">Uploading and Managing</a></li>
    <li><a href="../docs/python/tools/uploadingdata.html">Uploading Data</a></li>
    <li><a href="../docs/python/tools/webapp/index.html">webapp Framework</a>
      <ul>
             <li><a href="../docs/python/tools/webapp/overview.html">Overview</a></li>
     <li><a href="../docs/python/tools/webapp/running.html">Running the Application</a></li>
     <li><a href="../docs/python/tools/webapp/requesthandlers.html">Request Handlers</a></li>
     <li><a href="../docs/python/tools/webapp/requestdata.html">Request Data</a></li>
     <li><a href="../docs/python/tools/webapp/buildingtheresponse.html">Building the Response</a></li>
     <li><a href="../docs/python/tools/webapp/redirects.html">Redirects, Headers and Status Codes</a></li>
     

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/tools/webapp/requestclass.html">Request</a></li>
         <li><a href="../docs/python/tools/webapp/responseclass.html">Response</a></li>
         <li><a href="../docs/python/tools/webapp/requesthandlerclass.html">RequestHandler</a></li>
         <li><a href="../docs/python/tools/webapp/wsgiapplicationclass.html">WSGIApplication</a></li>
         <li><a href="../docs/python/tools/webapp/utilmodule.html">Utility Functions</a></li>
         
       </ul>
     </li>

      </ul>
    </li>
    <li><a href="../docs/python/tools/libraries.html">Third-party Libraries</a></li>

      </ul>
    </li>
    <li><a href="../docs/python/howto/index.html">How-To</a>
      <ul>
              <li><a href="../docs/python/howto/usinggdataservices.html">Google Data Services</a></li>

      </ul>
    </li>

    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Managing Your App</h2>
    <ul>
      <li><a href="../docs/theadminconsole.html">The Admin Console</a></li>
      <li><a href="../docs/quotas.html">Quotas</a></li>
      <li><a href="../docs/billing.html">Billing</a></li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Resources</h2>
    <ul>
      <li><a href="../kb/index.html">FAQ</a></li>
      <li><a href="index.html">Articles</a></li>
      <li><a href="http://appengine-cookbook.appspot.com/">Cookbook</a></li>
      <li><a href="http://appgallery.appspot.com/">App Gallery</a></li>
      <li><a href="http://code.google.com/p/googleappengine/">SDK Code</a></li>
      <li><a href="http://code.google.com/p/google-app-engine-samples/">Sample Apps Code</a></li>
      <li><a href="../community.html">Discussion Groups</a></li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><a href="../docs/roadmap.html">Product Roadmap</a></li>
  <li><a href="http://code.google.com/p/googleappengine/wiki/SdkReleaseNotes">Release Notes</a></li>
  <li><a href="../docs/revision_history.html">Revision History</a></li>
</ul>

        <a class="hidden" href="#gc-topnav-anchor">More Google App Engine resource links</a>
      </div>
      
      <a name="gc-pagecontent-anchor"></a>   
      <div class="g-unit" id="gc-pagecontent">
        <script type="text/javascript">CODESITE_docEarlyProcessing();</script>
        <h1 class="page_title">HOWTO: Create a Facebook App with Google App Engine and Best Buy Remix</h1>


<div id="jd-content">
<div class="jd-descr">
<p class="note">
This article was written and submitted by an external contributor.
The Google App Engine team thanks Omar Abdelwahed for his time and expertise.
</p>
<i>Omar Abdelwahed</i><br>
<i>January 17, 2009</i>

<h2>Introduction</h2>

<p>Creating a Facebook application can be an exercise in gleaning arcane knowledge from multiple online sources. In particular, it is often hard to find an example of what should be a common practice: hosting a Facebook app on Google AppEngine. This article will attempt to turn the &quot;arcane&quot; into everyday knowledge and provide a useful example by integrating Best Buy's Remix API and iLike's Music API to search for music products that users of our application can listen to and then purchase.</p>

<h2>What You Need...</h2>

<p>We won't cover all the basics of setting up individual platforms and API's for use but rather concentration on the integration points. If you are new to any of the following, be sure the read the corresponding startup guides:</p>

<ol>
  <li>Google AppEngine &quot;Getting Started&quot;: <a href="http://code.google.com/appengine/docs/python/gettingstarted/">http://code.google.com/appengine/docs/python/gettingstarted/</a></li>
  <li>Facebook &quot;Creating your first application&quot;: <a href="http://wiki.developers.facebook.com/index.php/Creating_your_first_application">http://wiki.developers.facebook.com/index.php/Creating_your_first_application</a></li>
  <li>Best Buy Remix &quot;Getting started is easy&quot;: <a href="http://remix.bestbuy.com">http://remix.bestbuy.com</a></li>
  <li>iLike Developer Signup: <a href="http://www.ilike.com/developer/signup">http://www.ilike.com/developer/signup</a></li>
</ol>

<p>For each of the above, you'll need to register and utilize the corresponding API keys where required.</p>

<p class="note"><strong>Note:</strong>This article assumes the developer is working locally on Windows (and sitting comfortably at his or her favorite caf&eacute;), however this is not required (the caf&eacute; is however). Most of what is covered will easily translate to your development environment of choice. Windows-specific items will be noted where possible.</p>

<h2>Sample Code...</h2>

<p>Download the source code for our example application here:</p>

<a href="http://code.google.com/p/shelftalkers/">http://code.google.com/p/shelftalkers/</a>

<p>Place the project in a location of your choice. We'll refer to this code throughout the article.</p>

<h2>Host on Google AppEngine...</h2>

<p>Assuming you've downloaded AppEngine (if not, before sure to read the guide above), go to your project source directory and open <code>shelftalkers.py</code> in your favorite IDE or text editor. (Python's IDLE was installed as part of your development environment in Google's &quot;Getting Started&quot; guide.) At the top of <code>shelftalkers.py</code> are four API keys that you need to fill out.</p>

<ul>
  <li><strong><code>_FbApiKey</code></strong>: This is the API key provided by Facebook when you create a new app. More on this below.</li>
  <li><strong><code>_FbSecret</code></strong>: This is your FB app's secret key. Never share this outside your server hosted code. This is also provided by Facebook for each app you create.</li>
  <li><strong><code>_BestBuyRemixKey</code></strong>: This is API key to access Best Buy's full product catalog and store information. Amongst the many features, it lets you find products in stores near you and online at BestBuy.com. This key is provided to you when you register as a developer for Best Buy Remix. You can use either &quot;development&quot; or &quot;production&quot; keys here. Of course, use production keys when you release your app to the public.</li>
  <li><strong><code>_iLikeDevKey</code></strong>: Like Remix, this is the API key to access iLike's streaming music API. You receive this key when you register as a developer.</li>
</ul>

<p>Take a look at the top declarations of <code>shelftalker.py</code>. Most of the imported libraries are explained in Google's &quot;Getting Started&quot; guide. The others are described here:</p>

<ul>
  <li><strong><code>import xml.etree.cElementTree</code></strong>: We use this library to parse returned XML data from API calls to Remix.</li>
  <li><strong><code>import facebook</code></strong>: This is the Python wrapper for calls to the Facebook API. You can find this wrapper inside the <code>facebook.py</code> source file.</li>
</ul>

<p>Save your code changes.</p>

<p>On Windows, open a command line to launch AppEngine locally. AppEngine starts using the installed <code>dev_appserver.py</code> server. Enter this command substituting the paths for both your local AppEngine install and ShelfTalker's source code:</p>

<pre>google_appengine/dev_appserver.py shelftalkers/</pre>

<p>You should now have a local copy of AppEngine running on <a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a>. Don't try to browse this just yet. We need to create your app on Facebook next!</p>

<h2>Create Your Facebook App...</h2>

<p>In order to create applications on Facebook, you have to install Facebook's Developer Application. The Developer Application is the hub where your applications are defined and developers can commune with one another. (Again, you can read all about this in the above guide.)</p>

<p>Click the &quot;Set Up New Application&quot; button at the top of the Developer Application page.</p>
<br/>
<img src="img/newfbapp.png" alt="Facebook: Set Up New Application"/>

<p>You can now define the properties of your application: its name and integration points into users' profiles, for example. Two things we'll concern ourselves with now are the &quot;Callback URL&quot; and &quot;Render Method&quot; (under Canvas Settings). The Callback URL will eventually point to your code hosted on Google AppEngine. For our example (and likely most of the applications you create like this), we'll set the Render Method to &quot;IFrame&quot; which allows us more freedom in our app implementation.</p>

<p>For now, do the following:</p>

<ol>
  <li>Enter <a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a> for the Callback URL. This will allow you to test your code on your local copy of AppEngine before uploading to production.</li>
  <li>Choose &quot;IFrame&quot; for the Render Method.</li>
  <li>Add an application name, canvas URL and any other properties you wish to define. You can always come back and change these settings later.</li>
  <li>Save your changes. Facebook will note where there is any missing information for the basic application to run. Make changes where indicated.</li>
  <li>Copy and paste the new API key and Secret key provided by Facebook into the locations described above in <code>shelftalkers.py</code>. Save your changes. AppEngine will automatically detect the changes and serve them.</li>
</ol>

<p>Now, for the moment of truth. Facebook applications are addressed by their canvas URL. For example: <a href="http://apps.facebook.com/shelftalkers/">http://apps.facebook.com/shelftalkers/</a> where &quot;shelftalkers&quot; is replaced by what you provided in your FB app's settings. Be sure you are logged into Facebook, and enter your app's canvas URL into your browser. If all goes well, you'll see your app running locally!</p>

<p>Of course, not everything goes as plan. Some basic trouble-shooting tips:</p>

<ul>
  <li>If you get a &quot;404&quot; error or &quot;page is missing&quot; or &quot;unavailable&quot;, check that AppEngine is running locally and that you provided <a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a> as the Callback URL in your app settings.</li>
  <li>If you get code errors, you can view these in your browser or in the command shell running AppEngine. Codes errors <em>should be</em> limited to incorrect API keys.</li>
  <li>If something more is afoot, check your startup guides for help. They detail everything we need to run our application.</li>
</ul>

<h2>The Application: ShelfTalkers...</h2>

<p>So we have a running application on Facebook and Google AppEngine. What does it do? Glad you asked... &quot;ShelfTalkers&quot; has a basic premise. Users enjoy entertainment like music and they wish to start conversations around what they love. A simple text box lets people talk about their favorite music artist and attach sample music to their comments. This is posted to their Facebook pages for others to read, listen and continue the discussion.</p>

<p>Our basic application uses the Best Buy Remix API to search for the products first, so that later we can provide locations for users to make purchases. The returned search list feeds the iLike API to return associated music streams for the artists found. In the end, a sample Facebook post, including cover art, music sample and comment is shown for the user to choose to post to his or her page.</p>

<p>Note that our basic application is not feature complete. It is meant as a start primarily to teach how to create and host a Facebook application on Google AppEngine and provide a simple example of the Best Buy Remix API and iLike API. What is missing?</p>

<ul>
  <li>Mini-feed postings of the actual comments. This is a fairly advanced topic and covered in a number of locations on Facebook. See the &quot;Where To Go From Here&quot; links below.</li>
  <li>Buy links! iLike provides a few online choices, but it would be nice to locate a Best Buy store near users for that immediate purchase. Remix provides an interface to query product availability by store location by a user's zip code. You can see examples of how to do this on the Remix documentation page: <a href="http://remix.bestbuy.com/docs">http://remix.bestbuy.com/docs</a></li>
</ul>

<h2>Production Hosting: Google AppEngine...</h2>

<p>Now that your app works locally, we need to share it with the world! Uploading your app to Google AppEngine is well described in the &quot;Getting Started&quot; guide here: <a href="http://code.google.com/appengine/docs/python/gettingstarted/uploading.html">http://code.google.com/appengine/docs/python/gettingstarted/uploading.html</a>.</p>

<p>The one thing to note is what you call your app on AppEngine. Open the <code>app.yaml</code> file in your source directory. The first line marked &quot;application&quot; is the name of your app. You must change this to correspond to the name you define on AppEngine at <a href="http://appengine.google.com">http://appengine.google.com</a>. AppEngine will provide you with an URL to call your application. It will be of the following form (substitute your new application-id):</p>

<p><a href="http://appengine.google.com">http://application-id.appspot.com/</a></p>

<p>Follow the directions to upload your app. Go back to your Facebook application settings and replace the Callback URL with this new URL on AppEngine. Save your changes and you are now serving your Facebook application on Google AppEngine.</p>

<h2>Where To Go From Here...</h2>

<p>Here are some sources for more advanced development.</p>

<p>Searching with the Best Buy Remix API:<br/>
<a href="http://remix.bestbuy.com/docs">http://remix.bestbuy.com/docs</a></p>

<p>Facebook Feeds and Posting Stories:<br/>
<a href="http://wiki.developers.facebook.com/index.php/Feed">http://wiki.developers.facebook.com/index.php/Feed</a></p>

<p>jQuery and AJAX:<br/>
<a href="http://docs.jquery.com/Ajax">http://docs.jquery.com/Ajax</a></p>

<p>PyFacebook -- Python Wrapper:<br/>
<a href="http://wiki.developers.facebook.com/index.php/PythonPyFacebookTutorial">http://wiki.developers.facebook.com/index.php/PythonPyFacebookTutorial</a><br/>
<a href="http://code.google.com/p/pyfacebook/">http://code.google.com/p/pyfacebook/</a></p>

<h3>About the Author...</h3>

<div style="float: left; padding-bottom: 5px; padding-right: 5px;">
<a href="http://profile.ak.facebook.com/v230/437/62/s795684099_2864.jpg"><img src="img/omar.png" alt="Omar Abdelwahed " style="border: 1px solid black;" height="55" width="55"></a>
</div>

<p>Omar Abdelwahed is a Producer at Ubisoft Entertainment. His work focuses on producing games for social networks and connecting devices that are proliferating today's world. (In short, he gets paid to play with Facebook on his iPhone.) While at Best Buy, Omar led the development of the Remix Open API (<a href="http://remix.bestbuy.com/">http://remix.bestbuy.com/</a>) that allows mashup developers access to Best Buy's product catalog and store information.</p>

<p>Omar can be contacted at the following sites...</p>

<p>Twitter: <a href="http://twitter.com/appleweed">appleweed</a><br/>
Facebook: Omar Abdelwahed<br/>
<div style="float:left;">Web:&nbsp;</div><div style="float:left;"><a href="http://code.google.com/p/shelftalkers/">http://code.google.com/p/shelftalkers/</a><br/>
<a href="http://www.agentdisco.com">http://www.agentdisco.com</a></div></p><p></p>

</div>
</div>
   
      </div><!-- end gc-pagecontent -->
   </div><!-- end gooey wrapper -->

    </div> <!-- end codesite content -->

<div id="gc-footer" dir="ltr">
  <div class="text">
    
      <div class="notice"><div id="notice" style="text-align: center; border: 1em 0em 1em 0em">
  Except as otherwise <a
  href="http://code.google.com/policies.html#restrictions">noted</a>,
  the content of this page is licensed under the <a rel="license"
  href="http://creativecommons.org/licenses/by/2.5/">Creative Commons
  Attribution 2.5 License</a>, and code samples are licensed under the
  <a rel="license" href="http://www.apache.org/licenses/LICENSE-2.0">Apache
  2.0 License</a>.
<!-- <rdf:RDF xmlns="http://web.resource.org/cc/" 
              xmlns:dc="http://purl.org/dc/elements/1.1/"
              xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <Work rdf:about="">
    <license rdf:resource="http://creativecommons.org/licenses/by/2.5/" />
  </Work>
  <License rdf:about="http://creativecommons.org/licenses/by/2.5/">
    <permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
    <permits rdf:resource="http://web.resource.org/cc/Distribution"/>
    <requires rdf:resource="http://web.resource.org/cc/Notice"/>
    <requires rdf:resource="http://web.resource.org/cc/Attribution"/>
    <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
  </License>
</rdf:RDF> -->
</div>
Java is a registered trademark of Sun Microsystems, Inc.</div>
    
    &copy;2009 Google -
    <a href="http://code.google.com">Code Home</a> -
    <a href="http://www.google.com/accounts/TOS">Terms of Service</a> -
    <a href="http://www.google.com/privacy.html">Privacy Policy</a> -
    <a href="http://code.google.com/more">Site Directory</a>
    <br /> <br />
    Google Code offered in:
    <a href="http://code.google.com/intl/en">English</a> -
    <a href="http://code.google.com/intl/es">Español</a> -
    <a href="http://code.google.com/intl/ja">日本語</a> -
    <a href="http://code.google.com/intl/ko">한국어</a> -
    <a href="http://code.google.com/intl/pt-BR">Português</a> -
    <a href="http://code.google.com/intl/ru">Pусский</a> -
    <a href="http://code.google.com/intl/zh-CN">中文(简体)</a> -
    <a href="http://code.google.com/intl/zh-TW">中文(繁體)</a>
  </div>
</div><!-- end gc-footer -->

</div><!-- end gc-containter -->

<script type="text/javascript">CODESITE_CSITimer['load'].tick('ats');</script>
<script src="../../js/codesite_tail.pack.04102009.js" type="text/javascript"></script>






  </body>
</html>


